/**
 * 
 */
package fhq.hcmute.qrcode.common;

import java.io.UnsupportedEncodingException;

import fhq.hcmute.qrcode.util.AlphanumericTable;

/**
 * @author Hien Nguyen Le
 * @Email: nglehien@gmail.com
 */
public enum DataMode {
	NUMERIC("0001", new int[] { 10, 12, 14 }), ALPHANUMERIC("0010", new int[] {
			9, 11, 13 }), BINARY("0100", new int[] { 8, 16, 16 });

	private String value;
	private int[] characterBitsCount;

	private DataMode(String value, int[] characterBitsCount) {
		this.value = value;
		this.characterBitsCount = characterBitsCount;
	}

	public static DataMode chooseMode(String content) {
		if (isNumericMode(content)) {
			return NUMERIC;
		} else if (isAlphanumericMode(content)) {
			return ALPHANUMERIC;
		}
		return BINARY;
	}

	private static boolean isNumericMode(String content) {
		int count = 0;
		for (int i = 0; i < content.length(); ++i) {
			char c = content.charAt(i);
			if (c >= '0' && c <= '9') {
				count++;
			}
		}
		if (count == content.length()) {
			return true;
		}
		return false;
	}

	private static boolean isAlphanumericMode(String content) {
		int count = 0;
		for (int i = 0; i < content.length(); ++i) {
			char c = content.charAt(i);
			if (AlphanumericTable.getValueByChar(c) != -1) {
				count++;
			}
		}
		if (count == content.length()) {
			return true;
		}
		return false;
	}

	public String getValue() {
		return value;
	}

	public int getTotalBitRespective(String contents) {
		int length = contents.length();
		if (this.equals(NUMERIC)) {
			if (length % 3 == 0) {
				return (length / 3) * 10;
			} else if (length % 3 == 2) {
				return (length / 3) * 10 + 7;
			} else if (length % 3 == 1) {
				return (length / 3) * 10 + 4;
			}
		} else if (this.equals(ALPHANUMERIC)) {
			if (length % 2 == 0) {
				return length / 2 * 11;
			} else if (length % 2 == 1) {
				return (length / 2) * 11 + 6;
			}
		}
		try {
			length = contents.getBytes("UTF-8").length;
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return length * 8;
	}

	public int getTotalBitRespective(int length) {
		if (this.equals(NUMERIC)) {
			if (length % 3 == 0) {
				return (length / 3) * 10;
			} else if (length % 3 == 2) {
				return (length / 3) * 10 + 7;
			} else if (length % 3 == 1) {
				return (length / 3) * 10 + 4;
			}
		} else if (this.equals(ALPHANUMERIC)) {
			if (length % 2 == 0) {
				return length / 2 * 11;
			} else if (length % 2 == 1) {
				return (length / 2) * 11 + 6;
			}
		}
		return length * 8;
	}

	public int getCharacterCount(Version version) {
		if (version.getVersionNumber() <= 9) {
			return characterBitsCount[0];
		} else if (version.getVersionNumber() <= 26) {
			return characterBitsCount[1];
		}
		return characterBitsCount[2];
	}

	public static DataMode parse(String mode) {
		for (DataMode dataMode : values()) {
			if (dataMode.value.equals(mode)) {
				return dataMode;
			}
		}
		return null;
	}
}
